package Actions;

import java.awt.event.ActionEvent;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JScrollBar;
import javax.swing.KeyStroke;
//import javax.swing.event.CaretEvent;
//import javax.swing.event.CaretListener;

public class Events {

	private TypeWriter.TypeWriter parent;
	private Room.Room editor;
	
	private JScrollBar vscroll;
	
	// start 'er up
	public Events( TypeWriter.TypeWriter parent, Actions.Windows windowSystem, Room.Room editor )
	{
		this.parent = parent;
		this.editor = editor;
		
		initModifiedCallback();
		
		
		vscroll = parent.getScroller().getVerticalScrollBar();
		vscroll.addAdjustmentListener(scrollChange);
	}
	

	// inits the rooms modification callback
	private void initModifiedCallback()
	{
		editor.setModifiedCallback(new Callback(){

			@Override
			public boolean callback() {
				parent.changeTitle();
				return false;
			}
			
		});
	}
	
	// handle closing
	public WindowListener wnd = new WindowAdapter() {
		@Override
		public void windowClosing( WindowEvent e )
		{
			parent.getWindowSys().closeDisposeWindow();
		}
	};
	
	public void setKeyBindings()
	{

		if(parent.getOptions().hardcore){
			parent.getEvents().enterHardcore();
//			parent.getEditor().getCaret().setDot(dot);
		}
		editor.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_MASK), "openFile");
		editor.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_MASK), "newFile");
		editor.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_MASK), "saveFile");
		editor.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_MASK+KeyEvent.ALT_MASK), "saveFileAs");
		editor.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_B, KeyEvent.CTRL_MASK), "changeBG");
		editor.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F, KeyEvent.CTRL_MASK), "changeFG");
		editor.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_T, KeyEvent.CTRL_MASK), "changeFont");
		editor.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_Q, KeyEvent.CTRL_MASK), "quit");
		editor.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_K, KeyEvent.CTRL_MASK), "openOptions");
		editor.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_H, KeyEvent.CTRL_MASK), "openHelp");
		
		editor.getActionMap().put("openFile",openFile);
		editor.getActionMap().put("newFile",newFile);
		editor.getActionMap().put("saveFile",saveFile);
		editor.getActionMap().put("saveFileAs",saveFileAs);
		editor.getActionMap().put("changeBG",changeBG);
		editor.getActionMap().put("changeFG",changeFG);
		editor.getActionMap().put("changeFont",changeFont);
		editor.getActionMap().put("quit",quit);
		editor.getActionMap().put("openOptions",openOptions);
		editor.getActionMap().put("openHelp",openHelp);
		
		
		editor.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE,0), "toggleFullScreen");
		editor.getActionMap().put("toggleFullScreen",toggleFullScreen);
		
		
		
	}

	// enter hardcore mode
	public void enterHardcore()
	{
		editor.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_A, KeyEvent.CTRL_MASK), "none");
		editor.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_H, KeyEvent.CTRL_MASK), "none");
		editor.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE,0), "none");
		editor.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE,0), "none");
		editor.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME,0), "none");
		editor.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_END,0), "none");
		

		editor.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN,0), "down");
		editor.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_UP,0), "up");
		editor.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT,0), "none");
		editor.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,0), "none");
		editor.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP,0), "bigup");
		editor.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN,0), "bigdown");
		

		editor.getActionMap().put("down",down);
		editor.getActionMap().put("up",up);
		editor.getActionMap().put("bigup",bigUp);
		editor.getActionMap().put("bigdown",bigDown);
		
//		editor.addCaretListener(stopCaret);
		editor.addMouseListener(stopMouse);
	}

	// toggle fullscreen
	Action toggleFullScreen = new AbstractAction("toggleFullScreen") {
		private static final long serialVersionUID = 1L;

		@Override
        public void actionPerformed(ActionEvent e) {
        	parent.getWindowSys().toggleFullScreen();
        }
    };
	// open a file
	Action openFile = new AbstractAction("openFile") {
		private static final long serialVersionUID = 1L;

		@Override
        public void actionPerformed(ActionEvent e) {
        	parent.getFiles().openFile();
        }
    };
	// newFile a file
	Action newFile = new AbstractAction("newFile") {
		private static final long serialVersionUID = 1L;

		@Override
        public void actionPerformed(ActionEvent e) {
        	parent.getFiles().newFile();
        }
    };
	// saveFile a file
	Action saveFile = new AbstractAction("saveFile") {
		private static final long serialVersionUID = 1L;

		@Override
        public void actionPerformed(ActionEvent e) {
			parent.getFiles().saveFile( editor.getFilePath() );
        }
    };
	// saveFileAs a file
	Action saveFileAs = new AbstractAction("saveFileAs") {
		private static final long serialVersionUID = 1L;

		@Override
        public void actionPerformed(ActionEvent e) {
			parent.getFiles().saveFileAs();
        }
    };
	// changeFG
	Action changeFG = new AbstractAction("changeFG") {
		private static final long serialVersionUID = 1L;

		@Override
        public void actionPerformed(ActionEvent e) {
			parent.getOptions().chooseForeground();
        }
    };
	// changeBG
	Action changeBG = new AbstractAction("changeBG") {
		private static final long serialVersionUID = 1L;

		@Override
        public void actionPerformed(ActionEvent e) {
			parent.getOptions().chooseBackground();
        }
    };
	// changeFont
	Action changeFont = new AbstractAction("changeFont") {
		private static final long serialVersionUID = 1L;

		@Override
        public void actionPerformed(ActionEvent e) {
			parent.getOptions().chooseFont();
        }
    };
	// quit a file
	Action quit = new AbstractAction("quit") {
		private static final long serialVersionUID = 1L;

		@Override
        public void actionPerformed(ActionEvent e) {
			parent.getWindowSys().closeDisposeWindow();
        }
    };

	// open a file
	Action down = new AbstractAction("down") {
		private static final long serialVersionUID = 1L;

		@Override
        public void actionPerformed(ActionEvent e) {
        	changeIsUser(true);
        	smallDown();
        }
    };

	// open a file
	Action up = new AbstractAction("up") {
		private static final long serialVersionUID = 1L;

		@Override
        public void actionPerformed(ActionEvent e) {
        	changeIsUser(true);
        	smallUp();
        }
    };

	// open a file
	Action bigDown = new AbstractAction("bigDown") {
		private static final long serialVersionUID = 1L;

		@Override
        public void actionPerformed(ActionEvent e) {
        	changeIsUser(true);
        	goDown();
        }
    };

	// open a file
	Action bigUp = new AbstractAction("bigUp") {
		private static final long serialVersionUID = 1L;

		@Override
        public void actionPerformed(ActionEvent e) {
        	changeIsUser(true);
        	goUp();
        }
    };
	// open options dialog
	Action openOptions = new AbstractAction("openOptions") {
		private static final long serialVersionUID = 1L;

		@Override
        public void actionPerformed(ActionEvent e) {
        	parent.getOptions().showOptionDialog();
        }
    };
	// open help dialog
	Action openHelp = new AbstractAction("openHelp") {
		private static final long serialVersionUID = 1L;

		@Override
        public void actionPerformed(ActionEvent e) {
        	parent.getOptions().showHelpDialog();
        }
    };
    
    // sets whether change is caused by user
	public void changeIsUser(boolean is)
	{		
		// sets if the user is changing the scroll position
		parent.getWindowSys().setUser(is);
	}
	
	// listen for events on the keyboard
	public KeyListener key = new KeyAdapter() {
		public void keyPressed(KeyEvent e)
		{
			if(  Character.isLetterOrDigit(e.getKeyChar()) || Character.isWhitespace(e.getKeyChar()) && !e.isControlDown() )
			{
				editor.setModified( true );
				parent.getWindowSys().playSound();
			}
		}
		public void keyReleased(KeyEvent e)
		{
			changeIsUser(false);
		}
	};
	
	// hardcore up/down/page up/page down
	private void goUp()
	{
		changeIsUser(true);
		vscroll.setValue( vscroll.getValue() - parent.getHeight() );
	}
	private void goDown()
	{
		changeIsUser(true);
		vscroll.setValue( vscroll.getValue() + parent.getHeight() );
	}
	private void smallUp()
	{
		changeIsUser(true);
		vscroll.setValue( vscroll.getValue() - editor.getLineHeight() );
	}
	private void smallDown()
	{
		changeIsUser(true);
		vscroll.setValue( vscroll.getValue() + editor.getLineHeight() );
	}
	
	
	// add scroll without scrollbars
	public MouseWheelListener mouseWheel = new MouseWheelListener() {
		@Override
		public void mouseWheelMoved(MouseWheelEvent e) {
			int count = e.getWheelRotation();

			changeIsUser(true);
			vscroll.setValue( vscroll.getValue() + count * 35 );
			changeIsUser(false);
		}
	};
	
	// used for typewriter scrolling
	public AdjustmentListener scrollChange = new AdjustmentListener() {
		
		@Override
		public void adjustmentValueChanged(AdjustmentEvent arg0) {
			boolean bigEnough = (vscroll.getMaximum() > parent.getHeight()*2);
			if( parent.getWindowSys().isFull() && !bigEnough ){
				parent.getWindowSys().scrollPos = vscroll.getMaximum() - vscroll.getValue();
				return;
			}
				
			if(!parent.getWindowSys().getUser() && parent.getOptions().typewriterScroll ){
				vscroll.setValue( vscroll.getMaximum() - parent.getWindowSys().scrollPos );
			}
			parent.getWindowSys().scrollPos = vscroll.getMaximum() - vscroll.getValue();
		}
	};

	// only used in hardcore
	public MouseListener stopMouse = new MouseListener() {

		@Override
		public void mouseClicked(MouseEvent arg0) {
			return;
		}

		@Override
		public void mouseEntered(MouseEvent arg0) {
			return;
		}

		@Override
		public void mouseExited(MouseEvent arg0) {
			return;
		}

		@Override
		public void mousePressed(MouseEvent arg0) {
			editor.setEnabled(false);
			
		}

		@Override
		public void mouseReleased(MouseEvent arg0) {
			editor.setEnabled(true);
			editor.getCaret().setDot(editor.getDocument().getLength());
		}

		
	};
	
}
